//
//  STInnerAlertController.swift
//  iPhone
//
//  Created by Toj on 5/27/22.
//

import UIKit
import SnapKit
import SDWebImage

typealias STActionHandle = (()->Void)
private let cornerRadius: CGFloat = 8
class STInnerAlertController: UIViewController {
    
    public var alertModel: STAlertModel?
    public var defalutAction: STActionHandle? = nil
    public var cancelAction: STActionHandle? = nil
    public var effectAction: STActionHandle? = nil
    
    public init(alertModel: STAlertModel) {
        super.init(nibName: nil, bundle: nil)
        self.alertModel = alertModel
    }
    
    // 是否自动适配方向
    override open var shouldAutorotate: Bool {
        return false
    }
    
    // 适配方向
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
    
    private override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        super.modalPresentationStyle = .custom
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(backgroundView)
        view.addSubview(alertView)
        view.addSubview(imageView)
        
        // 第一次布局显示弹窗内容, 不包含图片
        setupLayoutSubviews()
        // 设置UI内容
        setupSubviews()
    }
    
    private func setupSubviews() {
        guard let model = alertModel else { return }
        alertView.alertModel = alertModel
        let corners: CACornerMask = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
        alertView.cm_corner(radius: cornerRadius, corners: corners)
        
        let urlString = model.topPicUrl
        guard urlString.count > 0 else { return }
        
        let url = URL(string: urlString)
        imageView.sd_setImage(with: url) { [weak self] image, error, type, url in
            let size = image?.size ?? .zero
            self?.imageCompletion(size: size)
        }
    }
    
    private func imageCompletion(size: CGSize) {
        guard let model = alertModel else { return }
        
        let iWidth = size.width
        let iHeight = size.height
        imageView.isHidden = iWidth == 0 || iHeight == 0
        if imageView.isHidden { return }
        
        let corners: CACornerMask = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
        alertView.cm_corner(radius: cornerRadius, corners: corners)
        
        let height = iHeight * model.contentWidth / iWidth
        alertModel?.imageHeight = height
        // 图片回来后2次布局, 主要布局图片大小, UI动画
        resetupLayoutSubviews()
    }
    
    private func resetupLayoutSubviews() {
        setupLayoutSubviews()
        view.setNeedsLayout()
        UIView.animate(withDuration: 0.15) {
            self.view.layoutIfNeeded()
        }
    }
    
    @objc private func didTapBackground(sender: UITapGestureRecognizer) {
        let isClose = alertModel?.isEffectClose ?? false
        guard isClose else { return }
        dismissAlert(handle: effectAction)
    }
    
    private func dismissAlert(handle: (()->Void)? = nil) {
        dismiss(animated: false) {
            handle?()
        }
    }
    
    private lazy var imageView: UIImageView = {
        let view = UIImageView()
        view.isHidden = true
        return view
    }()
    
    private lazy var backgroundView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor.black.withAlphaComponent(0.6)
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapBackground(sender:)))
        view.addGestureRecognizer(tapGesture)
        return view
    }()
    
    private lazy var alertView: STAlertView = {
        let view = STAlertView()
        view.delegate = self
        return view
    }()
    
    private func setupLayoutSubviews(to size: CGSize = .zero) {
        
        let kHeight = size == .zero ? UIScreen.main.bounds.height : size.height
        let kWidth = size == .zero ? UIScreen.main.bounds.width : size.width
        let sWidth = 280 * kWidth / 360
        let alertWidth: CGFloat = sWidth > 280 ? 280 : sWidth
        let alertHeight = alertModel?.alertHeight(max: alertWidth) ?? 0
        let imageHeight = alertModel?.imageHeight ?? 0
        let top = (kHeight - alertHeight - imageHeight) * 0.5
        imageView.snp.remakeConstraints { make in
            make.width.equalTo(alertWidth)
            make.centerX.equalTo(view)
            make.height.equalTo(imageHeight)
            make.top.equalTo(top)
        }
        
        alertView.snp.remakeConstraints { make in
            make.width.equalTo(alertWidth)
            make.centerX.equalTo(view)
            make.height.equalTo(alertHeight)
            make.top.equalTo(imageView.snp.bottom)
        }
        
        backgroundView.snp.remakeConstraints { make in
            make.edges.equalTo(view)
        }
    }
    
    deinit {
        // print("-->toj: " + #function + " name: STInnerAlertController")
    }
}

extension STInnerAlertController: STAlertViewDelegate {
    
    func alertViewImageLoaded(_ view: STAlertView) {
        // 记录下图片已经load完
        alertModel?.imageLoaded = true
        
        resetupLayoutSubviews()
    }
    
    func alertView(_ view: STAlertView, didTapDefault: UIView) {
        dismissAlert(handle: defalutAction)
    }
    
    func alertView(_ view: STAlertView, didTapCancel: UIView) {
        dismissAlert(handle: cancelAction)
    }
}

protocol STAlertViewDelegate: NSObjectProtocol {
    
    func alertViewImageLoaded(_ view: STAlertView)
    func alertView(_ view: STAlertView, didTapDefault: UIView)
    func alertView(_ view: STAlertView, didTapCancel: UIView)
}

extension STAlertView: STAlertViewDelegate {
    
    func alertViewImageLoaded(_ view: STAlertView) { }
    func alertView(_ view: STAlertView, didTapDefault: UIView) { }
    func alertView(_ view: STAlertView, didTapCancel: UIView) { }
}

class STAlertView: UIView {
    
    public weak var delegate: STAlertViewDelegate?
    
    public var alertModel: STAlertModel? {
        didSet {
            guard let model = alertModel else { return }
            
            // 标题
            titleLable.text = model.title
            titleLable.isHidden = model.title.isEmpty
            titleLable.font = model.titleFont
            // 提示内容描述
            descriptionLable.text = model.popDescription
            descriptionLable.isHidden = model.popDescription.isEmpty
            descriptionLable.font = model.descriptionFont
            // button文字
            cancelLabel.text = model.cancelTitle
            cancelButton.isHidden = !model.isCancel
            
            defaultLabel.text = model.defalutTitle
            defaultLabel.textAlignment = model.isCancel ? .right : .center
            
            let urlString = model.popUrl
            if urlString.isEmpty { return }
            layoutIfNeeded()
            let url = URL(string: urlString)
            imageView.sd_setImage(with: url) { [weak self] image, error, type, url in
                if error != nil { return }
                self?.imageLoaded()
            }
        }
    }
    
    private func imageLoaded() {
        imageView.isHidden = false
        delegate?.alertViewImageLoaded(self)
        relayoutSubView()
    }
    
    @objc private func didTapDefault() {
        delegate?.alertView(self, didTapDefault: defaultButton)
    }
    
    @objc private func didTapCancel() {
        delegate?.alertView(self, didTapCancel: cancelButton)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        
        addSubview(titleLable)
        addSubview(descriptionLable)
        addSubview(cancelButton)
        addSubview(defaultButton)
        addSubview(imageView)
        
        cancelButton.addSubview(cancelLabel)
        defaultButton.addSubview(defaultLabel)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        setupLayoutSubviews()
    }
    
    private func relayoutSubView() {
        guard let model = alertModel else { return }
        
        imageView.snp.remakeConstraints { make in
            make.centerX.equalTo(self)
            make.width.height.equalTo(model.logoWH)
            make.bottom.equalTo(defaultButton.snp.top).offset(-model.logoSpacing)
        }
        
        var spacing = model.spacing
        if !imageView.isHidden {
            spacing = model.logoWH + model.logoSpacing * 2
        }
        descriptionLable.snp.remakeConstraints { make in
            make.left.equalTo(16)
            make.right.equalTo(snp.right).offset(-16)
            make.bottom.equalTo(defaultButton.snp.top).offset(-spacing)
            make.height.equalTo(model.descriptionHeight)
        }
    }
    
    private func setupLayoutSubviews() {
        guard let model = alertModel else { return }
        
        let buttons = model.isCancel ? [cancelLabel, defaultLabel] : [defaultLabel]
        let viewWidth = frame.width
        var width = viewWidth
        if buttons.count > 0 {
            width = viewWidth / CGFloat(buttons.count)
        }
        
        var top: CGFloat = 0
        if model.contentNotImage { top = 8 }
        titleLable.snp.remakeConstraints { make in
            make.left.equalTo(16)
            make.right.equalTo(snp.right).offset(-16)
            make.top.equalTo(model.spacing + top)
            make.height.equalTo(model.titleHeight)
        }
        
        cancelButton.snp.remakeConstraints { make in
            make.left.equalTo(self)
            make.width.equalTo(width)
            make.height.equalTo(model.buttonHeight-8)
            make.bottom.equalTo(self.snp.bottom).offset(-8)
        }
        
        defaultButton.snp.remakeConstraints { make in
            make.right.equalTo(self)
            make.width.height.bottom.equalTo(cancelButton)
        }
        
        relayoutSubView()
        
        cancelLabel.snp.remakeConstraints { make in
            make.centerY.equalTo(cancelButton)
            make.left.equalTo(20)
            make.right.equalTo(cancelButton.snp.right).offset(-5)
        }
        
        let rightMargin = buttons.count == 1 ? 5 : 30
        defaultLabel.snp.remakeConstraints { make in
            make.top.bottom.equalTo(cancelLabel)
            make.left.equalTo(5)
            make.right.equalTo(defaultButton.snp.right).offset(-rightMargin)
        }
    }
    
    private lazy var titleLable: UILabel = {
        let view = UILabel()
        view.numberOfLines = 0
        view.textAlignment = .center
        view.textColor = UIColor(hex: 0x212121)
        return view
    }()
    
    private lazy var descriptionLable: UILabel = {
        let view = setupLabels()
        view.numberOfLines = 0
        view.textAlignment = .center
        view.textColor = UIColor(hex: 0x666666)
        return view
    }()
    
    private lazy var cancelLabel: UILabel = {
        let view = setupLabels()
        view.textColor = UIColor(hex: 0x333333)
        return view
    }()
    
    private lazy var defaultLabel: UILabel = {
        let view = setupLabels()
        view.textAlignment = .right
        view.textColor = UIColor(hex: 0x0087EB)
        return view
    }()
    
    private func setupLabels() -> UILabel {
        let view = UILabel()
        view.numberOfLines = 2
        view.font = UIFont.boldSystemFont(ofSize: 14)
        view.autoresizesSubviews = false
        view.adjustsFontSizeToFitWidth = false
        view.lineBreakMode = .byTruncatingTail
        return view
    }
    
    private lazy var cancelButton: UIButton = {
        let view = UIButton()
        view.addTarget(self, action: #selector(didTapCancel), for: .touchUpInside)
        return view
    }()

    private lazy var defaultButton: UIButton = {
        let view = UIButton()
        view.addTarget(self, action: #selector(didTapDefault), for: .touchUpInside)
        return view
    }()
    
    private lazy var imageView: UIImageView = {
        let view = UIImageView()
        view.isHidden = true
        return view
    }()
    
    deinit {
        //print("-->toj: " + #function + " name: STAlertView")
    }
}
